﻿/*----------------------------------------------------------------
// Copyright (C) 2005 麦迪斯顿(北京)医疗科技发展有限公司
// 文件名：DataEntityContainer.cs
// 文件功能描述：DataEntityContainer
// 创建标识：顾伟伟-2011-01-14
----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Light.Common.Mapping;
using System.Data.Common;

namespace Light.Data.DataEntity
{
    /// <summary>
    /// 数据实体容器，用于缓存映射关系
    /// </summary>
   public class DataEntityContainer
    {
       private static readonly Dictionary<Type, DataFieldCollection> _cache = new Dictionary<Type, DataFieldCollection>();

       private static readonly Dictionary<Type, DataEntityCommand> _commandCache = new Dictionary<Type, DataEntityCommand>();

       /// <summary>
       /// 根据实体类型，从缓存中返回实体的映射数据
       /// </summary>
       /// <param name="entityType"></param>
       /// <returns></returns>
       public static DataFieldCollection GetEntityMappings(Type entityType)
       {
           if (!_cache.ContainsKey(entityType))
           {
               _cache[entityType] = BuildEnityMappings(entityType);
           }
           return _cache[entityType];
       }
       /// <summary>
       /// 根据实体属性描述，生成实体的映射数据
       /// </summary>
       /// <param name="entityType"></param>
       public static DataFieldCollection BuildEnityMappings(Type entityType)
       {
           DataFieldCollection fields = new DataFieldCollection();

           var dataAttribute = entityType.GetCustomAttributes(typeof(DataEntityAttribute), true);

           if (dataAttribute != null && dataAttribute.Length == 1)
           {
               var table = dataAttribute[0] as DataEntityAttribute;
               fields.TableName= table.TableName;
           }

           var props = entityType.GetProperties();

           foreach (var prop in props)
           {
               var filedAttribute = prop.GetCustomAttributes(typeof(DataFieldAttribute), true);
               if (filedAttribute != null && filedAttribute.Length == 1)
               {
                   var dataFiled = filedAttribute[0] as DataFieldAttribute;
                   fields.FieldMappings.Add(prop, dataFiled);
               }
           }
           
           return fields;
           
       }
       /// <summary>
       /// 根据映射关系，生成实体类更新的InsertCommand,UpdateCommand
       /// </summary>
       /// <param name="fieldMappings"></param>
       /// <returns></returns>
       public static  DataEntityCommand GetEntityCommand(Type entityType,IDatabase databse)
       {
           if (!_commandCache.ContainsKey(entityType))
           {
               _commandCache[entityType] = BuildEntityCommand(entityType, databse);
           }
           else
           {
               _commandCache[entityType].ResetParameters();
           }

           return _commandCache[entityType];
       }

       /// <summary>
       /// 生成实体类的InsertCommandText,UpdateCommandText
       /// </summary>
       /// <param name="fieldMappings"></param>
       /// <returns></returns>
       public static DataEntityCommand BuildEntityCommand(Type entityType,IDatabase database)
       {
           var fieldMappings = GetEntityMappings(entityType);

           DataEntityCommand entityCommand = new DataEntityCommand(database);

           var insertFields = string.Empty;
           var insertFieldValues = string.Empty;
           var updateFiledAndValues = string.Empty;
           var condition = string.Empty;

           List<DbParameter> dbParameter = new List<DbParameter>();
           List<string> primaryKeys = new List<string>();

           foreach (var field in fieldMappings.FieldMappings)
           {
               if (string.IsNullOrEmpty(insertFields))
                   insertFields += field.Value.ColumnName;
               else
                   insertFields += " , " + field.Value.ColumnName;

               if (string.IsNullOrEmpty(insertFieldValues))
                   insertFieldValues += database.CreateDbParameterName(field.Value.ColumnName);
               else
                   insertFieldValues += " , " + database.CreateDbParameterName(field.Value.ColumnName);

               if (string.IsNullOrEmpty(updateFiledAndValues))
                   updateFiledAndValues += string.Format("{0}={1}", field.Value.ColumnName, database.CreateDbParameterName(field.Value.ColumnName));
               else
                   updateFiledAndValues += string.Format(" , {0}={1}", field.Value.ColumnName, database.CreateDbParameterName(field.Value.ColumnName));

               if (field.Value.PrimaryKey)
               {
                   if (string.IsNullOrEmpty(condition))
                       condition += string.Format("{0}={1}", field.Value.ColumnName, database.CreateDbParameterName(field.Value.ColumnName));
                   else
                       condition += string.Format(" and {0}={1}", field.Value.ColumnName, database.CreateDbParameterName(field.Value.ColumnName));
                   primaryKeys.Add(field.Value.ColumnName);
               }

               entityCommand.Parameters[field.Value.ColumnName] = database.BuildDbParameter(field.Value.ColumnName, field.Value.DbType);
           }

           entityCommand.PrimaryKeys = primaryKeys.ToArray();
           entityCommand.UpdateCommand = string.Format("Update {0} Set {1} Where {2}", fieldMappings.TableName, updateFiledAndValues, condition);
           entityCommand.InsertCommand = string.Format("Insert into {0} ( {1} ) Values( {2} )", fieldMappings.TableName, insertFields, insertFieldValues);
           entityCommand.DeleteCommand = string.Format("Delete from {0} Where {1}", fieldMappings.TableName, condition);

           return entityCommand;
       }
    }
}
